package hsb.ruoyi.common.core.domain.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.usthe.sureness.subject.PrincipalMap;
import com.usthe.sureness.subject.Subject;
import com.usthe.sureness.subject.SubjectSum;
import com.usthe.sureness.subject.support.SurenessSubjectSum;
import io.quarkus.runtime.annotations.RegisterForReflection;

import java.util.LinkedHashMap;
import java.util.List;

/**
 * @author 胡帅博
 * @date 2023/1/2 19:06
 */
//@JsonTypeInfo(
//        use = JsonTypeInfo.Id.CLASS,
//        include = JsonTypeInfo.As.PROPERTY,
//        property = "className"
//)
@RegisterForReflection
//@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "loginUser")
public class JwtSubject implements Subject {

    private static final long serialVersionUID = 1L;

    /**
     * appId
     **/
   // @JsonDeserialize(as= LoginUser.class)
    private LoginUser loginUser;

    /**
     * json web token
     **/
    private String jwt;

    /**
     * remote ip
     **/
    private String remoteHost;

    /**
     * remote device
     **/
    private String userAgent;

    /**
     * the roles which this user owned
     **/
    private List<String> ownRoles;

    /**
     * the uri resource which this user want access
     **/
    private String targetUri;

    /**
     * the Roles which can access this resource above-targetUri
     **/
    private List<String> supportRoles;

    /**
     * the map for principal, add your custom principal
     **/
    @JsonIgnore
    private PrincipalMap principalMap;


    public JwtSubject() {

    }

//    public LoginUser getLoginUser() {
//        return loginUser;
//    }
//
//    public void setLoginUser(LoginUser loginUser) {
//        this.loginUser = loginUser;
//    }

    private JwtSubject(Builder builder) {
        this.loginUser = builder.loginUser;
        this.jwt = builder.jwt;
        this.remoteHost = builder.remoteHost;
        this.userAgent = builder.userAgent;
        this.ownRoles = builder.ownRoles;
        this.supportRoles = builder.supportRoles;
        this.targetUri = builder.targetUri;
        this.principalMap = builder.principalMap;
    }

  //  @JsonDeserialize(as= LoginUser.class)
    @Override
    public Object getPrincipal() {
        return this.loginUser;
    }

   // @JsonDeserialize(as= LoginUser.class)
    @Override
    public void setPrincipal(Object var1) {

        //这个是解决傻逼框架 非要在这里用set Object 导致jackson序列化成 LinkedHashMap
        if (var1 instanceof LinkedHashMap){

        }else {
            this.loginUser = (LoginUser) var1;
        }
    }


    @Override
    public PrincipalMap getPrincipalMap() {
        return this.principalMap;
    }

    @Override
    public void setPrincipalMap(PrincipalMap var1) {
        this.principalMap = var1;
    }

    @Override
    public Object getCredential() {
        return this.jwt;
    }

    @Override
    public void setCredential(Object var1) {
        this.jwt = (String) var1;
    }

    @Override
    public Object getOwnRoles() {
        return this.ownRoles;
    }

    @SuppressWarnings("unchecked")
    @Override
    public void setOwnRoles(Object var1) {
        this.ownRoles = (List<String>) var1;
    }

    @Override
    public Object getTargetResource() {
        return this.targetUri;
    }

    @Override
    public void setTargetResource(Object var1) {
        this.targetUri = (String) var1;
    }

    @Override
    public Object getSupportRoles() {
        return this.supportRoles;
    }

    @SuppressWarnings("unchecked")
    @Override
    public void setSupportRoles(Object var1) {
        this.supportRoles = (List<String>) var1;
    }

    public String getRemoteHost() {
        return remoteHost;
    }

    public String getUserAgent() {
        return userAgent;
    }

    public static Builder builder(String jwt) {
        return new Builder(jwt);
    }

    public static Builder builder(Subject subject) {
        return new Builder(subject);
    }

    public static class Builder {

        private LoginUser loginUser;
        private String jwt;
        private String remoteHost;
        private String userAgent;
        private List<String> ownRoles;
        private String targetUri;
        private List<String> supportRoles;
        private PrincipalMap principalMap;

        public Builder(String jwt) {
            this.jwt = jwt;
        }

        @SuppressWarnings("unchecked")
        public Builder(Subject subject) {
            this.loginUser = (LoginUser) subject.getPrincipal();
            this.jwt = String.valueOf(subject.getCredential());
            this.ownRoles = (List<String>) subject.getOwnRoles();
            this.targetUri = String.valueOf(subject.getTargetResource());
            this.supportRoles = (List<String>) subject.getSupportRoles();
            this.principalMap = subject.getPrincipalMap();
        }

        public Builder setPrincipal(LoginUser loginUser) {
            this.loginUser = loginUser;
            return this;
        }

        public Builder setPrincipalMap(PrincipalMap principalMap) {
            this.principalMap = principalMap;
            return this;
        }

        public Builder setCredentials(String jwt) {
            this.jwt = jwt;
            return this;
        }

        public Builder setTargetResource(String targetUri) {
            this.targetUri = targetUri;
            return this;
        }

        public Builder setOwnRoles(List<String> ownRoles) {
            this.ownRoles = ownRoles;
            return this;
        }

        public Builder setSupportRoles(List<String> supportRoles) {
            this.supportRoles = supportRoles;
            return this;
        }

        public Builder setRemoteHost(String remoteHost) {
            this.remoteHost = remoteHost;
            return this;
        }

        public Builder setUserAgent(String userAgent) {
            this.userAgent = userAgent;
            return this;
        }

        public JwtSubject build() {
            return new JwtSubject(this);
        }

    }

    public static final SubjectSum successSubjectSum = SurenessSubjectSum.builder().build();

    public SubjectSum generateSubjectSummary() {
        return successSubjectSum;
    }
}
